package estatistica;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;

import simpackNew.Const;

public class Dispersion {
    public static File directory;
    
    // Files list
    public static File[] fileListClassA;
    public static File[] fileListClassB;

    // Filtering class pattern
    public static final String PATTERN_A = "classA";
    public static final String PATTERN_B = "classB";

    // Output
    public static FileWriter writerA;
    public static PrintWriter outputA;
    public static FileWriter writerB;
    public static PrintWriter outputB;
    public static FileWriter writer;
    public static PrintWriter output;

    // Input
    public static FileReader reader;
    public static BufferedReader input;

    public static double rounder(double number) {
	int decimalPlace = 2;
	BigDecimal bd = new BigDecimal(number);
	bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
	number = bd.doubleValue();

	return number;
    }

    /**
     * It Calculates de pattern deviations of a array
     * 
     * @param inData - Array with data to be calculate the deviation.
     * @param P - Percentage of classA users
     * @param contract - Contract variation
     * @param classType - Class of service
     * @param politics - Politics type
     * @param dataType - Fulfilment ou Latencies below average
     */
    public static void calculateDeviation(double[] inData, int P, int contract, String classType, String politics, int dataType) {
	double variance, deviation;
	double additionOfTheSquares = 0.0;
	double sum = 0.0;
	int n = 0;
	String fileName = "";

	// Calculates Variance
	for(double value : inData) {
	    sum += value;
	    additionOfTheSquares += (value * value);
	    n++;
	}
	variance = (additionOfTheSquares - ((sum * sum) / n)) / (n - 1);
	deviation = Math.sqrt(variance);

	
	// Opens Output file
	try {
	    switch(dataType) {
	    case Const.LATENCIES_BELOW_AVERAGE:
		directory = new File(new File(new File(Const.DATA_DIR), Const.LATENCIES_BELOW_AVERAGE_DIR), P + "");
		fileName = "latenciesBelowAverage_Class";
		break;
		
	    case Const.FULFILMENT_PERCENTAGE:
		directory = new File(new File(new File(Const.DATA_DIR), Const.FULFILMENT_DIR), P + "");
		fileName = "fulfilmentPercentage_Class";
		break;

	    default:
		System.out.println("Calculatin Deviation: Incorrect type of date"); 
	    	System.exit(1);
	    }
	    
	    if (!directory.exists())
		directory.mkdirs();

	    writer = new FileWriter(new File(directory, fileName + classType + "_" + P + "p_" + politics + ".txt"), true);
	    output = new PrintWriter(new BufferedWriter(writer));
	    
	    
	    /**
	     * Fulfilment File:
	     * 	[CONTRACT TYPE] \tab [MEAN] \tab [DEVIATION]
	     * */
	    output.println(contract + "\t" + rounder(sum / n) + "\t" + rounder(deviation));
	    
	    // Closes file
	    output.close();
	    writer.close();
	    
	} catch (IOException e) {
	    System.err.println(e);
	    System.exit(1);
	}

    }

    
    /**
     * It Calculates de pattern deviations of the data of a file
     * 
     * @param fileName - Name of a file with data to be processed.
     * @param output - Output stream where the result will be wrote.
     */
    public static void calculateDeviation(File fileName, PrintWriter output) {
	String line = null;
	double value, variance, deviation;
	double additionOfTheSquares = 0.0;
	double sum = 0.0;
	int n = 0;

	// It Opens reading Stream
	try {
	    reader = new FileReader(fileName);
	    input = new BufferedReader(reader);
	} catch (FileNotFoundException e) {
	    System.err.println(e);
	    System.exit(2);
	}

	// It Processes Data
	try {
	    while ((line = input.readLine()) != null) {
		value = Double.parseDouble(line.trim());
		sum += value;
		additionOfTheSquares += (value * value);
		n++;
	    }
	    variance = (additionOfTheSquares - ((sum * sum) / n)) / (n - 1);
	    deviation = Math.sqrt(variance);

	    // It writes result
	    // [CONTRACT TYPE] \tab [MEAN] \tab [DEVIATION]
	    output.println(fileName.getName().split("_")[2].split("c")[0]
		    + "\t" + rounder(sum / n) + "\t" + rounder(deviation));
	} catch (IOException e) {
	    System.err.println(e);
	    System.exit(3);
	}

	// It Closes reading Stream
	try {
	    input.close();
	    reader.close();
	} catch (IOException e) {
	    System.err.println(e);
	    System.exit(4);
	}
    }

    public static void processDirectory(String directoryName) {
	// ClassA's filter
	FilenameFilter filterClassA = new FilenameFilter() {
	    public boolean accept(File dir, String name) {
		return name.contains(PATTERN_A);
	    }
	};
	// ClassB's filter
	FilenameFilter filterClassB = new FilenameFilter() {
	    public boolean accept(File dir, String name) {
		return name.contains(PATTERN_B);
	    }
	};

	directory = new File(directoryName);
	fileListClassA = directory.listFiles(filterClassA);
	fileListClassB = directory.listFiles(filterClassB);

	try {
	    String P = directoryName
		    .substring(directoryName.lastIndexOf('\\') + 1);
	    writerA = new FileWriter(new File(directory,
		    "comportamento_ClassA_" + P + "p.txt"));
	    outputA = new PrintWriter(new BufferedWriter(writerA));
	    writerB = new FileWriter(new File(directory,
		    "comportamento_ClassB_" + P + "p.txt"));
	    outputB = new PrintWriter(new BufferedWriter(writerB));
	} catch (IOException e) {
	    System.err.println(e);
	    System.exit(1);
	}

	if (fileListClassA != null) {
	    for (int i = 0; i < fileListClassA.length; i++) {
		calculateDeviation(fileListClassA[i], outputA);
	    }
	} else {
	    System.out.println("Lista de arquivos Vazia!");
	}

	if (fileListClassB != null) {
	    for (int i = 0; i < fileListClassB.length; i++) {
		calculateDeviation(fileListClassB[i], outputB);
	    }
	} else {
	    System.out.println("Lista de arquivos Vazia!");
	}

	try {
	    outputA.close();
	    writerA.close();
	    outputB.close();
	    writerB.close();
	} catch (IOException e) {
	    System.err.println(e);
	}
    }

    public static void main(String[] args) {
	// 10% A, 90% B
	Dispersion.processDirectory("C:\\Documents and Settings\\SONY\\Desktop\\Mestrado\\workspace\\Simpack_Project\\Data\\Fulfilment Percentages\\10");

	// 50% A, 50% B
	Dispersion.processDirectory("C:\\Documents and Settings\\SONY\\Desktop\\Mestrado\\workspace\\Simpack_Project\\Data\\Fulfilment Percentages\\50");

	// 90% A, 10% B
	Dispersion.processDirectory("C:\\Documents and Settings\\SONY\\Desktop\\Mestrado\\workspace\\Simpack_Project\\Data\\Fulfilment Percentages\\90");
    }
}
